package com.bash.carrep.dao.general;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 *
 * @author bash
 */
public class CRUD {

    protected EntityTransaction utx = null;
    private EntityManagerFactory emf = null;
    private EntityManager em;
    private static CRUD singleInstance = null;

    private CRUD() {
        emf = Persistence.createEntityManagerFactory("CarrepPU");
    }

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    /**
     * Return instance of CRUD class
     * @return Return instance of CRUD class
     */
    public static synchronized CRUD getInstance() {

        if (null == singleInstance) {
            singleInstance = new CRUD();
        }     
        return singleInstance;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {

        throw new CloneNotSupportedException();

    }

    /**
     *Return an Object that is already persist in the Database
     * @param object
     * @return Return an Object that is already persist in the Database
     */
    public Object persist(Object object) {
        if (!em.isOpen()) {
            start();
        }

        try {

            em.persist(object);
          
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        }

        return object;

    }

    /**
     * 
     * @param object
     * @return Return an object that have been updated from the database
     */
    public Object edit(Object o) {
        if (em.isOpen()) {
            start();
        }
        try {
            em.merge(o);
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        }
        return o;
    }

    /**
     * Remove an Object from Database
     * @param object
     */
    public void remove(Object object) {
        if (!em.isOpen()) {
            start();
        }
        try {
            em.remove(object);
          
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        }

    }
    
    
    public List getAll(Class c){
           if (!em.isOpen()) {
            start();
        }
         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(c));
            Query q = em.createQuery(cq);
           
            return q.getResultList();
       
        
    }
//------------------- UseFull---------------------------------------------------
     /**
     * Return a list of result
     * @param query - EJBQL Querry
     * @return - Return a list of result
     * @throws Exception
     */
   
    public List getList(Query q) throws Exception {
        if (!em.isOpen()) {
            start();
        }
        List user = q.getResultList();

        return user;
    }
    //--------------------------------------------------------------------------

    /**
     * Return a list of result
     * @param query - JPA query
     * @return - Return a list of result
     * @throws Exception
     */
    public List getList(String query) throws Exception {
        if (!em.isOpen()) {
            start();
        }

        Query q = em.createQuery(query);
        //     q.setParameter(param1, result1);
        List user = q.getResultList();

        return user;
    }

    public Object getSingle(String query) throws Exception {
        if (!em.isOpen()) {
            start();
        }

        Query q = em.createNamedQuery(query);
        //     q.setParameter(param1, result1);
        Object o = q.getSingleResult();

        return o;
    }

    /**
     * Return a list of result
     * @param query  - JPA query
     * @param param1  - jpa query's parameter
     * @param result1 - Object to cast
     * @return - Return a list of result
     * @throws Exception
     */
    public List getList(String query, String param1, Object result1) throws Exception {
        if (!em.isOpen()) {
            start();
        }

        Query q = em.createNamedQuery(query);
        q.setParameter(param1, result1);
        List user = q.getResultList();

        return user;
    }

    /**
     * Retrieve a Record from Database
     * @param query - jpa query name
     * @param param1 - jpa query's parameter
     * @param result1 - Object to cast
     * @return - return result
     * @throws Exception
     */
    public Object get(String query, String param1, Object result1) throws Exception {
        if (!em.isOpen()) {
            start();
        }
        Query q = em.createNamedQuery(query);
        q.setParameter(param1, result1);
        Object user = (Object) q.getSingleResult();

        return user;
    }


    public Object getSingle(Query q) throws Exception {  //EJBQL
        if (!em.isOpen()) {
            start();
        }
        Object user = q.getSingleResult();

        return user;
    }

     public int getCount(Class C) {
        if (!em.isOpen()) {
            start();
        }
        try {
           
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root rt = cq.from(C);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    /**
     * Begin Entity manager
     */
    public void start() {

        // TODO code application logic here
        em = emf.createEntityManager();
        em.getTransaction().begin();

        // return em;
    }

    /**
     *  Stop Entity manager
     */
    public void stop() {
        if (em.getTransaction().isActive()) {
            em.getTransaction().commit();
        }
        em.close();
    }
}
